/**
 * 关于Range对象http://goo.gl/6gSaK
 * selelction,range对象的封装
 * 插入内容
 * 事件响应
 */

(function($) {

    var triangle = window.triangle = {};


    var ua = $.browser;

    var utils = {

        extend: $.extend,

        getSelection: function() {
            var doc = window.document;
            return (doc.selection) ? doc.selection : window.getSelection();
        },

        getRange: function() {
            var selection = this.getSelection();
            var range = selection.getRangeAt ? (selection.rangeCount ? selection.getRangeAt(0) : null) : selection.createRange();

            return !range ? null : range;
        },



        createRange: (ua.msie ? function() {
            var range = document.body.createTextRange();
            //range.moveToElementText(this.);
            return range;
        } : function() {
            var range = document.createRange();
            //range.selectNodeContens(this.);
            return range;
        }),

        /**
         * 更新选区对象
         * @return {[type]} [description]
         */
        updateSelectRange: function() {
            if (ua.msie) {
                return function(range) {

                }
            }
        }



    };


    var dom = {

        getElement: function(id) {
            return document.getElementById(id);
        },

        createElement: function(tagName, attrs) {
            var ele = document.createElement(tagName);
            for (var k in attrs) {
                $(ele).attr(k, attrs[k]);
            };
            return ele;
        },

        replaceNode: function(newNode, oldNode) {
            var parent = oldNode.parentNode;
            if (parent) {
                parent.replaceChild(newNode, oldNode);
            };
        },

        /**
         * 判断指定的节点是否是第二个节点的祖先
         * @param  {[type]}  node1 [description]
         * @param  {[type]}  node2 [description]
         * @return {Boolean}       [description]
         */
        isAncestor: function(node1, node2) {
            if (!node1 || !node2) {
                return false;
            }
            if (node1.contains && node2.nodeType && !ua.webkit) {
                return node1.contains(node2) && node1 != node2; // ie
                // 的contains如果元素相等也为true
            } // W3C DOM Level 3
            if (node1.compareDocumentPosition && node2.nodeType) {
                return !!(node1.compareDocumentPosition(node2) & 16);
            } else if (node2.nodeType) {
                return !!this.getAncestorBy(node2, function(el) {
                    return el == node1;
                });
            }
            return false;
        },
    };

    dom.tagName = {
        IFRAME: 'iframe',
        DIV: 'div'
    };


    triangle.CommentBox = function(id, config) {
        var cfg = config || {};
        this.loaded = false;
        this.id = id;
        this.guid = +new Date();
        this.config = utils.extend(default_cfg, config);
        this.init();
    };

    var CommentBox = triangle.CommentBox;

    CommentBox.editors = {};

    CommentBox.editorsCount = 0;

    CommentBox.action = {};


    CommentBox.prototype = {


        constructor: function() {

        },

        on: function(event, fn) {
            var self = this;
            self.$node.on(event, function(e, data) {
                data = [e].concat(data);
                fn.apply(self, data);
            })
        },

        init: function() {
            var ele = dom.getElement(this.id);
            var container = dom.createElement(dom.tagName.DIV, {
                'class': 'editor ' + 'editor-' + this.guid,
                'style': ele.style.cssText + 'width:' + this.config.width + ';height:' + this.config.height + ';'
            });
            container.id = this.id;
            dom.replaceNode(container, ele);
            this.container = container;
            this.$node = $(container);
            this.setEditable(true);
            CommentBox.registerBox(this);
        },

        setEditable: function(status) {
            var box = this.container;
            if (status) {
                box.contentEditable = true;
            } else {
                box.contentEditable = false;
            };
            box.spellcheck = false;
        },

        /**
         * 可以扩展一下
         * @return {[type]} [description]
         */
        focus: function() {
            this.container.focus();
        },

        getRange: function() {
            this.focus();
            return utils.getRange();
        },

        ready: function(fn) {
            if (fn && this.loaded) {
                $(fn);
            }
        },

        /**
         * 可以增加回调方法
         * @param  {[type]} type [description]
         * @return {[type]}      [description]
         */
        getContent: function(type) {
            var content = this.container;
            switch (type) {
                case 'node':
                    return content;
                case 'html':
                    return content.innerHTML;
                default:
                    return content.textContent || content.innerText || '';
            };
        },

        updateLastSelectedRange: (ua.msie ? function(range) {
            this.lastSelectedRange = range || document.selection.createRange();
        } : function(range) {
            try {
                this.lastSelectedRange = range || utils.getSelection().getRangeAt(0).cloneRange();
            } catch (e) {
                this.focus();
            };
        }),

        /**
         * 检查当前内容的长度
         * @return {[type]} [description]
         */
        checkCurrentLength: function() {

        },

        /**
         * 取得选取所在的起始位置
         * @return {[type]} [description]
         */
        getSelectionOffset: function() {
            var content = this.container;
            if (ua.msie) {
                var selectionRange = document.selection.createRange();
                var selectionElement = selectionRange.parentElement();
                if (content == selectionElement || dom.isAncestor(content, selectionElement)) {
                    var range = document.body.createTextRange();
                    range.moveToElementText(content);
                    range.setEndPoint('EndToStart', selectionRange);
                    var start = range.text.length;
                    range.setEndPoint('EndToEnd', selectionRange);
                    var end = range.text.length;
                    return {
                        start: start,
                        end: end
                    };
                }
            } else if (content == document.activeElement || dom.isAncestor(content, document.activeElement)) {
                var selectionRange = window.getSelection().getRangeAt(0);
                var range = document.createRange();
                range.setStart(content, 0);
                range.setEnd(selectionRange.startContainer, selectionRange.startOffset);
                var start = range.toString().length;
                range.setEnd(selectionRange.endContainer, selectionRange.endOffset);
                var end = range.toString().length;
                return {
                    start: start,
                    end: end
                };
            }
            return null;
        },

        createRange: function() {
            return utils.createRange();
        },

        /**
         * 在指定位置插入一个range对象
         * http://goo.gl/0WAAU
         * @return {[type]} [description]
         */
        createRangeOn: (ua.msie ? function(start, end) {
            var range = this.createRange();
            var length = Math.min(end - start, range.text.length);
            if (length > 0) {
                var diff = 0;
                range.collapse(true);
                while (diff = start - range.text.length) {
                    range.moveEnd('character', diff);
                }
                range.collapse(false);
                range.moveEnd('character', length);
                while (diff = length - range.text.length) {
                    range.moveEnd('character', diff);
                }
            } else {
                range.collapse(true);
            };
            return range;
        } : function(start, end) {
            var range = this.createRange();
            var root = this.container;
            var node = root.firstChild;
            while (node) {
                var length = node.textContent.length;
                if (start > length) {
                    start -= length;
                    node = node.nextSibling;
                } else {
                    if (node.firstChild) {
                        node = node.firstChild;
                    } else {
                        range.setStart(node, start);
                        break;
                    }
                }
            };
            return range;
        }),

        setContent: function(value, type) {
            var original = this.getContent(),
                root = this.container;

            switch (type) {
                case 'node':
                    root.innerHTML = '';
                    root.appendChild(value);
                    this.lastSelectedRange = this.createRange();
                    this.lastSelectedRange.collapse(false);
                    break;
                case 'html':
                    root.innerHTML = value;
                    break;
                default:
                    root.innerHTML = this.escHTML(value);
                    break;
            };
            this.focus();
        },

        escHTML: function(value) {
            var code = {
                re_amp: /&/g,
                re_lt: /</g,
                re_gt: />/g,
                re_apos: /\x27/g,
                re_quot: /\x22/g
            };
            var entity = {
                re_amp: '&amp;',
                re_lt: '&lt;',
                re_gt: '&gt;',
                re_apos: '&#039;',
                re_quot: '&quot;'
            }
            for (var i in entity) {
                value = value.replace(code[i], entity[i]);
            }
            return value;
        },

        /**
         * 结尾处追加内容
         * @param  {[type]} value [description]
         * @param  {[type]} type  [description]
         * @return {[type]}       [description]
         */
        appendToContent: function(value, type) {
            var original = this.getContent();
            var root = this.container;
            switch (type) {
                case 'html':
                    value = F4A.utils.dom.parseHTML(value);
                case 'node':
                    if (root.childNodes.length == 1 && root.firstChild.tagName == 'BR') {
                        root.replaceChild(value, root.firstChild);
                    } else {
                        root.appendChild(value);
                    }
                    break;
                default:
                    if (root.childNodes.length == 1 && root.firstChild.tagName == 'BR') {
                        root.innerHTML = escHTML(value);
                    } else {
                        value = document.createTextNode(value);
                        root.appendChild(value);
                    }
                    break;
            }
            if (ua.ie) {
                var range = document.body.createTextRange();
                range.moveToElementText(container);
                range.collapse(false);
            } else {
                var range = document.createRange();
                range.selectNode(root.lastChild || container);
                range.collapse(false);
            }
            this.updateLastSelectedRange(range);
            //this.onContentChanged(original, this.getContent());
            //onComplete && onComplete.call(this);
        },

        /**
         *
         * @return {Boolean} [description]
         */
        hasSelectedRange: function() {
            var root = this.container;
            if (ua.msie) {
                try {
                    var selectionElement = document.selection.createRange().parentElement();
                    return root == selectionElement || dom.isAncestor(root, selectionElement);
                } catch (ex) {
                    return false;
                }
            } else {
                return root == document.activeElement || dom.isAncestor(root, document.activeElement);
            }
        },

        getHighlightedRange: function() {
            if (this.lastSelectedRange) {
                return this.lastSelectedRange;
            }
            if (this.hasSelectedRange()) {
                try {
                    if (ua.ie) {
                        if (document.selection.type == 'None') {
                            var root = this.container;
                            var temp = document.createElement('span');
                            var range = document.createRange();
                            root.appendChild(temp);
                            range.moveToElement(temp);
                            return range;
                        } else {
                            return document.selection.createRange();
                        }
                    }
                    var range = getSelection().getRangeAt(0).cloneRange();
                    if (ua.webkit) {
                        var ancestor = range.commonAncestorContainer;
                        return ancestor == document.activeElement || dom.isAncestor(document.activeElement, ancestor) ? range : null;
                    }
                    return range;
                } catch (ex) {
                    return null;
                }
            }
        },


        insertToContent: (ua.msie ? function(value, type, getRangeToFocus) {
            var original = this.getContent();
            var range = this.getHighlightedRange();
            var placeHolder = null;
            if (range == null) {
                var root = this.container;
                placeHolder = document.createElement('span');
                root.appendChild(placeHolder);
                range = document.body.createTextRange();
                range.moveToElementText(placeHolder);
            }
            switch (type) {
                case 'node':
                    if (placeHolder == null) {
                        var placeHolderId = +new Date();
                        range.select();
                        range.pasteHTML(['<span id="', placeHolderId, '"></span>'].join(''));
                        placeHolder = dom.getElementById(placeHolderId);
                    }
                    placeHolder.parentNode.insertBefore(value, placeHolder);
                    range.moveToElementText(placeHolder);
                    break;
                case 'html':
                    try {
                        range.pasteHTML(value);
                    } catch (ex) {}
                    break;
                default:
                    range.text = value;
                    break;
            }
            placeHolder && placeHolder.parentNode && placeHolder.parentNode.removeChild(placeHolder);
            getRangeToFocus = getRangeToFocus || function() {
                range.collapse(false);
                return range;
            };
            range = getRangeToFocus();
            this.focusToRange(range);
            //this.onContentChanged(original, this.getContent());
            //onComplete && onComplete.call(this);
        } : function(value, type, getRangeToFocus) {
            var original = this.getContent();
            var range = this.getHighlightedRange();
            var placeHolder = null;
            if (range == null) {
                var root = this.container;
                if (root.childNodes.length == 1 && root.firstChild.tagName == 'BR') {
                    root.removeChild(root.firstChild);
                }
                var _rangeHolder = document.createTextNode('!');
                root.appendChild(_rangeHolder);
                range = document.createRange();
                range.selectNode(_rangeHolder);
            }
            switch (type) {
                case 'node':
                    break;
                case 'html':
                    value = F4A.utils.dom.parseHTML(value);
                    break;
                default:
                    value = document.createTextNode(value);
                    break;
            }
            range.deleteContents();
            if (ua.firefox) {
                var node = value.lastChild || value;
                range.insertNode(value);
                range.selectNode(node);
            } else {
                range.insertNode(value);
            }
            getRangeToFocus = getRangeToFocus || function() {
                range.collapse(false);
                return range;
            };
            range = getRangeToFocus();
            this.focusToRange(range);
            //this.onContentChanged(original, this.getContent());
            //onComplete && onComplete.call(this);
        }),

        focusToRange: (ua.msie ? function(range) {
            range.select();
            this.updateLastSelectedRange.call(this, range);
        } : function(range) {
            window.getSelection().removeAllRanges();
            window.getSelection().addRange(range);
            this.updateLastSelectedRange.call(this, range);
            this.focus();
        }),

        updateCurrentLength: function() {

        }
    };



    CommentBox.getBox = function(id) {
        return CommentBox.editors[id];
    };

    CommentBox.registerBox = function(editor) {
        editor.loaded = true;
        CommentBox.editors[editor.id] = editor;
        CommentBox.editorsCount++;
    };


    var default_cfg = {

        width: '400px',

        height: '150px'
    };

    var maps = {};

    maps.button = {
        blod: '粗体',
        underline: '下划线'
    };

    default_cfg.toolbar = {

        id: 'toolbar',

        buttons: ['blod', 'underline'],

        b_prefix: 'toolbar-button'
    }

})(jQuery)